/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.projects.toolbox_basics_project.web.gwt.form.edition.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.genia.toolbox.basics.exception.BundledException;
import com.genia.toolbox.basics.exception.technical.TechnicalException;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.City;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.I18nDynamicString;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.Region;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.impl.CityImpl;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.impl.RegionImpl;
import com.genia.toolbox.projects.toolbox_basics_project.business.dao.CityBusinessDao;
import com.genia.toolbox.projects.toolbox_basics_project.business.dao.I18nSearchHelperDao;
import com.genia.toolbox.projects.toolbox_basics_project.business.dao.RegionBusinessDao;
import com.genia.toolbox.projects.toolbox_basics_project.spring.manager.CommonFormManager;
import com.genia.toolbox.projects.toolbox_basics_project.spring.manager.LanguageManager;
import com.genia.toolbox.projects.toolbox_basics_project.web.gwt.form.constant.CityFormKey;
import com.genia.toolbox.projects.toolbox_basics_project.web.gwt.form.edition.CityEditionFormProvider;
import com.genia.toolbox.web.gwt.basics.client.oracle.SimpleSuggestion;
import com.genia.toolbox.web.gwt.form.client.value.DataIdentifier;
import com.genia.toolbox.web.gwt.form.client.value.FormValues;
import com.genia.toolbox.web.gwt.form.client.value.impl.DataIdentifierImpl;
import com.genia.toolbox.web.gwt.form.client.value.impl.FormSimpleValueImpl;
import com.genia.toolbox.web.gwt.form.client.value.impl.FormValuesImpl;
import com.genia.toolbox.web.gwt.form.server.provider.impl.AbstractEditionForm;

/**
 * CityEditionForm.
 */
public class AbstractCityEditionFormProvider
    extends AbstractEditionForm
    implements CityEditionFormProvider
{

  /**
   * CityBusinessDao.
   */
  private CityBusinessDao cityBusinessDao;

  /**
   * RegionBusinessDao.
   */
  private RegionBusinessDao regionBusinessDao;

  /**
   * {@link CommonFormManager }.
   */
  private CommonFormManager commonFormManager;

  /**
   * i18nSearchHelperDao for i18n search.
   */
  private I18nSearchHelperDao i18nSearchHelperDao;

  /**
   * LanguageManager to know language used.
   */
  private LanguageManager languageManager;






  /**
   * retrieve the initial value of the object that is edited.
   * 
   * @param city
   *          city used
   * @return a FormValues filled
   * @throws TechnicalException
   *           if an error occured
   */
  public FormValues getInitialValue(City city)
      throws TechnicalException
  {

    FormValuesImpl fv = new FormValuesImpl();
    fv.setFormIdentifier(getFormIdentifier());
    if (city.getIdentifier() != null) {
      fv.setDataIdentifier(new DataIdentifierImpl(city.getIdentifier()));
    }

    FormSimpleValueImpl fsvi = new FormSimpleValueImpl();
    fsvi.setName(CityFormKey.NAME);
    fsvi.setValues(getCommonFormManager().createStringList(city.getName()));
    fv.addFormSimpleValue(fsvi);

    fsvi = new FormSimpleValueImpl();
    fsvi.setName(CityFormKey.REGION);
    fsvi.setValue(String.valueOf(city.getRegion().getIdentifier()));
    fv.addFormSimpleValue(fsvi);

    return fv;
  }



  /**
   * retrieve the initial value of the object that is edited.
   * 
   * @param dataIdentifier
   *          identifier to use to get initialValues
   * @return FormValues filled
   * @throws BundledException
   *           when an error occurs
   */
  public FormValues getInitialValue(DataIdentifier dataIdentifier)
      throws BundledException
  {
    if (dataIdentifier.getIdentifier() == null) {

      return getDefaultValues();

    }
    else {

      return getInitialValue(getCityBusinessDao().getCity(Long.valueOf(dataIdentifier.getIdentifier())));

    }

  }



  /**
   * save the form on the server.
   * 
   * @param newValues
   *          the new values entered by the user
   * @return the new values that have been saved
   * @throws BundledException
   *           when an error occurred
   */
  @Transactional(rollbackFor = { BundledException.class })
  @SuppressWarnings("unchecked")
  public FormValues saveForm(FormValues newValues)
      throws BundledException
  {
    DataIdentifier dataIdentifier = newValues.getDataIdentifier();

    I18nDynamicString name = getCommonFormManager().createI18nDynamicString(newValues.getFormSimpleValue(CityFormKey.NAME).getValues());
    String regionId = newValues.getFormSimpleValue(CityFormKey.REGION).getValue();

    City city;
    if (dataIdentifier.getIdentifier() == null) {
      city = new CityImpl();
    }
    else {
      city = getCityBusinessDao().getCity(Long.valueOf(dataIdentifier.getIdentifier()));
    }

    city.setName(name);
    if (regionId != null) {
      city.setRegion(getRegionBusinessDao().getRegion(Long.parseLong(regionId)));
    }

    if (dataIdentifier.getIdentifier() == null) {
      getCityBusinessDao().saveCity(city);
      newValues.getDataIdentifier().setIdentifier(String.valueOf(city.getIdentifier()));
    }
    else {
      getCityBusinessDao().updateCity(city);

    }

    return newValues;

  }



  /**
   * get the display string for a given value.
   * 
   * @param fieldName
   *          the field name
   * @param value
   *          the current value of the field
   * @return the string to display for the given value
   * @throws BundledException
   *           when an error occurred
   */
  @Override
  public String getDisplayString(String fieldName, String value)
      throws BundledException
  {

    if (CityFormKey.REGION.equals(fieldName)) {
      if (value == null) {
        return null;
      }

      Region region = getRegionBusinessDao().getRegion(Long.valueOf(value));
      return region.getName().getI18nValues().get(getLanguageManager().getCurrentLanguage()).getValue() + " - "
          + region.getCountry().getName().getI18nValues().get(getLanguageManager().getCurrentLanguage()).getValue();
    }

    return super.getDisplayString(fieldName, value);
  }



  /**
   * get suggestions for a field.
   * 
   * @param dataIdentifier
   *          the data identifier
   * @param fieldName
   *          the field name
   * @param query
   *          the current value of the field
   * @param limit
   *          the maximum number of response
   * @return the list of suggestion for the field
   * @throws BundledException
   *           when an error occurred
   */
  @Override
  public List<SimpleSuggestion> getSuggestions(DataIdentifier dataIdentifier, String fieldName, String query, int limit)
      throws BundledException
  {

    if (CityFormKey.REGION.equals(fieldName)) {
      final List<SimpleSuggestion> res = new ArrayList<SimpleSuggestion>();
      for (RegionImpl region : getI18nSearchHelperDao().searchNamable(RegionImpl.class, query)) {
        final SimpleSuggestion suggestion = new SimpleSuggestion();
        suggestion.setDisplayString(region.getName().getI18nValues().get(getLanguageManager().getCurrentLanguage()).getValue() + " - "
            + region.getCountry().getName().getI18nValues().get(getLanguageManager().getCurrentLanguage()).getValue());
        suggestion.setValue(region.getIdentifier().toString());
        res.add(suggestion);
      }
      return res;
    }
    return super.getSuggestions(dataIdentifier, fieldName, query, limit);
  }



  /**
   * getter for the cityBusinessDao property.
   * 
   * @return cityBusinessDao
   */
  public CityBusinessDao getCityBusinessDao()
  {
    return cityBusinessDao;
  }



  /**
   * setter for the cityBusinessDao property.
   * 
   * @param cityBusinessDao
   *          the cityBusinessDao to set
   */
  public void setCityBusinessDao(CityBusinessDao cityBusinessDao)
  {
    this.cityBusinessDao = cityBusinessDao;
  }



  /**
   * getter for the regionBusinessDao property.
   * 
   * @return regionBusinessDao
   */
  public RegionBusinessDao getRegionBusinessDao()
  {
    return regionBusinessDao;
  }



  /**
   * setter for the regionBusinessDao property.
   * 
   * @param regionBusinessDao
   *          the regionBusinessDao to set
   */
  public void setRegionBusinessDao(RegionBusinessDao regionBusinessDao)
  {
    this.regionBusinessDao = regionBusinessDao;
  }



  /**
   * getter for the commonFormManager property.
   * 
   * @return the commonFormManager
   */
  public CommonFormManager getCommonFormManager()
  {
    return commonFormManager;
  }



  /**
   * setter for the commonFormManager property.
   * 
   * @param commonFormManager
   *          the commonFormManager to set
   */
  public void setCommonFormManager(CommonFormManager commonFormManager)
  {
    this.commonFormManager = commonFormManager;
  }



  /**
   * getter for the i18nSearchHelperDao property.
   * 
   * @return i18nSearchHelperDao
   */
  public I18nSearchHelperDao getI18nSearchHelperDao()
  {
    return i18nSearchHelperDao;
  }



  /**
   * setter for the i18nSearchHelperDao property.
   * 
   * @param searchHelperDao
   *          to set
   */
  public void setI18nSearchHelperDao(I18nSearchHelperDao searchHelperDao)
  {
    i18nSearchHelperDao = searchHelperDao;
  }



  /**
   * getter for the languageManager property.
   * 
   * @return languageManager
   */
  public LanguageManager getLanguageManager()
  {
    return languageManager;
  }



  /**
   * setter for the languageManager property.
   * 
   * @param languageManager
   *          to set
   */
  public void setLanguageManager(LanguageManager languageManager)
  {
    this.languageManager = languageManager;
  }

}
